home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / SciAn / src / ScianPick.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  6KB  |  262 lines

  1. /*ScianPick.c
  2.   Picking system for spaces in SciAn
  3.   Eric Pepke
  4.   May 30, 1991
  5. */
  6.  
  7. #include "Scian.h"
  8. #include "ScianTypes.h"
  9. #include "ScianLists.h"
  10. #include "ScianWindows.h"
  11. #include "ScianSpaces.h"
  12. #include "ScianDraw.h"
  13. #include "ScianIDs.h"
  14. #include "ScianErrors.h"
  15. #include "ScianPick.h"
  16.  
  17. #define MAXNPICKS        400    /*Maximum # of pick tuples*/
  18.  
  19. /*Product of the next two cannot be greater than 32767*/
  20. #define MAXPICKEDOBJECTS    15    /*Maximum # of picked objects*/
  21. #define MAXPICKEDVERTICES    2000    /*Maximum # of picked vertices*/
  22.  
  23. #ifdef GRAPHICS
  24. static Matrix tempMatrix, pickMatrix;
  25. #endif
  26.  
  27. short curPickObject;            /*Current object being picked*/
  28. long bestPickVertex;
  29.  
  30. short pickBuffer[MAXNPICKS * 2 + 1];    /*Pick buffer*/
  31.  
  32. struct POS
  33.     {
  34.     ObjPtr object;
  35.     long maxIndex;
  36.     Bool anyPicked;
  37.     };
  38.  
  39. struct POS pickObjects[MAXPICKEDOBJECTS];    /*Pickable objects*/
  40.  
  41. short hits[MAXNPICKS];
  42.  
  43. void StartPick()
  44. /*Starts picking mode*/
  45. {
  46. #ifdef GRAPHICS
  47.     getmatrix(tempMatrix);
  48.     pick(pickBuffer, MAXNPICKS);
  49.     initnames();
  50.     loadname(-1);
  51.     curPickObject = -1;
  52.     MATCOPY(pickMatrix, Identity);
  53. #endif
  54. }
  55.  
  56. #ifdef PROTO
  57. void PickObject(ObjPtr object, int resolveType)
  58. #else
  59. void PickObject(object, resolveType)
  60. ObjPtr object;
  61. int resolveType;
  62. #endif
  63. /*Declares that object is about to be drawn for picking*/
  64. {
  65. #ifdef GRAPHICS
  66.     ++curPickObject;
  67.     if (curPickObject >= MAXPICKEDOBJECTS - 1)
  68.     {
  69.     ReportError("PickObject", "Too many objects to pick");
  70.     return;
  71.     }
  72.     
  73.     pickObjects[curPickObject] . object = object;
  74.     pickObjects[curPickObject] . maxIndex = 0;
  75.     pickObjects[curPickObject] . anyPicked = false;
  76.     loadname(curPickObject * MAXPICKEDVERTICES);
  77. #endif
  78. }
  79.  
  80. #ifdef PROTO
  81. void PickVertex(long vertex)
  82. #else
  83. void PickVertex(vertex)
  84. long vertex;
  85. #endif
  86. /*Identifies a vertex number for picking*/
  87. {
  88.     if (vertex > pickObjects[curPickObject] . maxIndex)
  89.     {
  90.     pickObjects[curPickObject] . maxIndex = vertex;
  91.     }
  92.     loadname(curPickObject * MAXPICKEDVERTICES +
  93.          vertex % MAXPICKEDVERTICES);
  94. }
  95.  
  96. void EndPickObject(object)
  97. ObjPtr object;
  98. /*Ends the picking for object*/
  99. {
  100. #ifdef GRAPHICS
  101.     loadname(-1);
  102. #endif
  103. }
  104.  
  105. #ifdef PROTO
  106. int CompareShorts(const void *a, const void *b)
  107. #else
  108. int CompareShorts(a, b)
  109. void *a, *b;
  110. #endif
  111. /*Compares two shorts for qsort*/
  112. {
  113.     return ((short *) a)[0] - ((short *) b)[0];
  114. }
  115.  
  116. ObjPtr StopPick()
  117. /*Stops picking mode and returns a list of objects*/
  118. {
  119. #ifdef GRAPHICS
  120.     int nHits, k, d, c;
  121.     ObjPtr retVal;
  122.     int whichObject;
  123.     long trimmedVertex;
  124.     long hitCounter;
  125.     int currentObject;
  126.     int tryVertex;
  127.     real px, py, pz;
  128.     FuncTyp method;
  129.     Matrix projMatrix, viewMatrix, curMatrix;
  130.     real xnew, ynew, znew, wnew;
  131.     real bestDist;
  132.     int bestVertex;
  133.     real r2;
  134.  
  135.     bestPickVertex = -1;
  136.     /*Get the current matrix for transformation*/
  137.  
  138.     mmode(MPROJECTION);
  139.     getmatrix(projMatrix);
  140.     mmode(MVIEWING);
  141.     getmatrix(viewMatrix);
  142.     MULTMATRIX(viewMatrix, projMatrix, curMatrix);
  143.  
  144.     /*Restore the old matrix*/
  145.     loadmatrix(tempMatrix);
  146.     nHits = endpick(pickBuffer);
  147.     if (nHits < 0)
  148.     {
  149.     ReportError("StopPick", "Pick buffer was too small");
  150.     nHits = -nHits;
  151.     }
  152.  
  153.     /*Go through the hits and distribute through the buffer*/
  154.     retVal = NULLOBJ;
  155.     if (nHits)
  156.     {
  157.     k = 0;
  158.     hitCounter = 0;
  159.     while (nHits)
  160.     {
  161.         c = pickBuffer[k];
  162.     
  163.         ++k;
  164.         while (c)
  165.         {
  166.         if (pickBuffer[k] >= 0)
  167.         {
  168.             hits[hitCounter++] = pickBuffer[k];
  169.         }
  170.         --c;
  171.         ++k;
  172.         }
  173.         --nHits;
  174.     }
  175. #if 0
  176.             whichObject = pickBuffer[k] / MAXPICKEDVERTICES;
  177.             trimmedVertex = pickBuffer[k] % MAXPICKEDVERTICES;
  178.             printf("%d ", trimmedVertex);
  179.             retVal = pickObjects[whichObject] . object;
  180. #endif
  181.  
  182.     /*Sort the hits*/
  183.     qsort(hits, hitCounter, sizeof(short), CompareShorts);
  184.  
  185.     /*Uniq them*/
  186.     d = 0;
  187.     for (k = 1; k < hitCounter; ++k)
  188.     {
  189.         if (hits[k] != hits[d])
  190.         {
  191.         ++d;
  192.         hits[d] = hits[k];
  193.         }
  194.     }
  195.     hitCounter = d + 1;
  196.  
  197.     /*Go through the hits and see which one is the closest*/
  198.     bestDist = PLUSINF;
  199.     currentObject = -1;
  200.     for (k = 0; k < hitCounter; ++k)
  201.     {
  202.         whichObject = hits[k] / MAXPICKEDVERTICES;
  203.         trimmedVertex = hits[k] % MAXPICKEDVERTICES;
  204.  
  205.         if (whichObject > currentObject)
  206.         {
  207.         currentObject = whichObject;
  208.         method = GetMethod(pickObjects[currentObject] . object,
  209.                 BEGINSTUFFING);
  210.         if (method)
  211.         {
  212.             (*method)(pickObjects[currentObject] . object);
  213.         }
  214.         else
  215.         {
  216.             retVal = pickObjects[currentObject] . object;
  217.         }
  218.         method = GetMethod(pickObjects[currentObject] . object,
  219.             STUFFSELPOINT);
  220.         }
  221.  
  222.         for (tryVertex = trimmedVertex;
  223.          tryVertex <= pickObjects[currentObject] . maxIndex;
  224.          tryVertex += MAXPICKEDVERTICES)
  225.         {
  226.         if (method)
  227.         {
  228.             (*method)(pickObjects[currentObject] . object,
  229.             tryVertex, &px, &py, &pz);
  230.  
  231.             xnew = px * curMatrix[0][0] + py * curMatrix[1][0] +
  232.                pz * curMatrix[2][0] +      curMatrix[3][0];
  233.  
  234.             ynew = px * curMatrix[0][1] + py * curMatrix[1][1] +
  235.                pz * curMatrix[2][1] +      curMatrix[3][1];
  236.  
  237.             znew = px * curMatrix[0][2] + py * curMatrix[1][2] +
  238.                pz * curMatrix[2][2] +      curMatrix[3][2];
  239.  
  240.             wnew = px * curMatrix[0][3] + py * curMatrix[1][3] +
  241.                pz * curMatrix[2][3] +      curMatrix[3][3];
  242.  
  243.             xnew /= wnew;
  244.             ynew /= wnew;
  245.             znew /= wnew;
  246.  
  247.             r2 = xnew * xnew + ynew * ynew;
  248.  
  249.             if (r2 < bestDist)
  250.             {
  251.             retVal = pickObjects[currentObject] . object;
  252.             bestPickVertex = tryVertex;
  253.             bestDist = r2;
  254.             }
  255.         }
  256.         }        
  257.     }
  258.     }
  259.     return retVal;
  260. #endif
  261. }
  262.